<template>
  <div style="width: 100%;height: 100%;display: flex">
    <div class="left_box">
      <div class="code_box">
        <ace-editor  style="width: 100%;height: 100%" :html-text-value="htmlStr" :ts-text-value="tsStr"></ace-editor>
      </div>
    </div>
    <div id="load4490_box">
      <div class="popup_box">
        <div class="inner_content_common">
          <el-button type="primary" @click="measureEvent('point')" size="small">绘制点</el-button>
          <el-button type="primary" @click="measureEvent('line')" size="small">绘制线</el-button>
          <el-button type="primary" @click="measureEvent('polygon')" size="small">绘制面</el-button>
          <el-button type="primary" @click="removeAll" size="small">清除所有</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {initMap} from "@/widgets/modelExample_cesium/common/initMap";
import {loadTdtLayer} from "@/widgets/modelExample_cesium/common/loadLayers";
import measurePoint from "@/widgets/modelExample_cesium/common/Measure/Point";
import measureLine from "@/widgets/modelExample_cesium/common/Measure/Polyline";
import measurePolygon from "@/widgets/modelExample_cesium/common/Measure/Polygon";

import AceEditor from "@/components/aceEditor.vue";

import {onMounted, ref} from "vue";
const cViewer = ref();
let point:any=null;
let polyline:any=null;
let polygon:any=null;

//修改天地图
const toolbar = ref({})
const htmlStr=ref(`
<template>
  <div style="width: 100%;height: 100%;display: flex">
    <div id="load4490_box">
      <div class="popup_box">
        <div class="inner_content_common">
          <el-button type="primary" @click="measureEvent('point')" size="small">绘制点</el-button>
          <el-button type="primary" @click="measureEvent('line')" size="small">绘制线</el-button>
          <el-button type="primary" @click="measureEvent('polygon')" size="small">绘制面</el-button>
          <el-button type="primary" @click="removeAll" size="small">清除所有</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {initMap} from "@/widgets/modelExample_cesium/common/initMap";
import {loadTdtLayer} from "@/widgets/modelExample_cesium/common/loadLayers";
import measurePoint from "@/widgets/modelExample_cesium/common/Measure/Point";
import measureLine from "@/widgets/modelExample_cesium/common/Measure/Polyline";
import measurePolygon from "@/widgets/modelExample_cesium/common/Measure/Polygon";
import {onMounted, ref} from "vue";

const cViewer = ref();
let point:any=null;
let polyline:any=null;
let polygon:any=null;

onMounted(() => {
  cViewer.value = initMap("load4490_box")
  loadTdtLayer(cViewer.value, 'c', false);
})
const measureEvent=(type:string)=>{
  let xoffset= document.body.clientWidth*0.4;
  if(type==='point'){
    point= new  measurePoint(cViewer.value);
    point.startMeasure({popOffset:{x:xoffset,y:72}})
  }else if(type==="line"){
    polyline= new  measureLine(cViewer.value);
    polyline.startMeasure({popOffset:{x:xoffset,y:72}})
  }else if(type==="polygon"){
    polygon= new  measurePolygon(cViewer.value);
    polygon.startMeasure({popOffset:{x:xoffset,y:72}})
  }
}
const removeAll=()=>{
  if(point){
    point.clearDrawGraphic();
  }
  if(polyline){
    polyline.clearDrawGraphic();
  }
  if(polygon){
    polygon.clearDrawGraphic();
  }
}
<\/script>

<style lang="scss" scoped>

#load4490_box {
  width: 60%;
  height: 100%;
}

.popup_box {
  position: fixed;
  left: calc(40% + 100px);
  width: 200px;
  top: 100px;
  height: 60px;
  z-index: 10;
}

.inner_content_common {
  margin-top: 10px;
  display: flex;
  justify-content: center;
  width: 50%;
}
</style>

`);
const tsStr=ref(`
//以测量面polygon为主
import * as Cesium from 'cesium';
import gisTools from '../GisTools';
import mouseHelper from '../MouseHelper';
//当前类使用的全局的viewer
let cviewer: any = {};
//当前类的事件句柄
let handler: any = {};
class MeasurePolygon {
  _drawingPolygon: any;
  _drawingPolyline: any;
  _drawingPositions: any;
  _drawingEntity:any;
  isDrawingEnd: any;
  constructor(viewer: any) {
    //绘制中的graphic-主要绘制活动的面使用   活动的面  --- 脏数据
    this._drawingPolygon = null;
    //活动的线
    this._drawingPolyline=null;
    //绘制中的geometry-主要绘制面、线使用  -数据类型 Cartesian3  ---脏数据
    this._drawingPositions = [];
    //绘制过程中顶点，以及点数不足三个点时的线都放在内部 --脏数据
    this._drawingEntity=[]
    //是否绘制结束
    this.isDrawingEnd = false;
    cviewer = viewer;
    handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  }

  /**
   * 开始绘制
   * @param bNeed  true | false  表示绘制动作是否是连续性的，即绘制完一个不结束，默认false
   * @param options  {
   *   "Polygon":{ fill:"填充颜色","opacity":"透明度"}
   *   "Polyline":{ "stroken":"线颜色","width":"线宽度" }   //绘制面的时候有填充
   *        "popOffset":{x:400,y:0}
   * }
   */
  startMeasure(options: any={}) {
    let _this = this;
    let { popOffset,Polyline,Polygon } = options;
    mouseHelper.createHelper({ x:-500,y:-500 }, '',popOffset);
    //左键事件
    handler.setInputAction(function(evt: any) {
      let car3 = gisTools.getCar3Position(cviewer,evt.position);
      if(car3){
        if(_this._drawingPositions.length===0){
          _this._drawingPositions.push(car3.clone());
        }
        _this._drawingPositions.push(car3);
        _this.createPoint(car3.clone());
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    //鼠标移动事件
    handler.setInputAction(function(evt: any) {
      let car3 = gisTools.getCar3Position(cviewer,evt.endPosition);
        if (_this._drawingPositions.length===0) {
          mouseHelper.updateHelper(evt.endPosition, '左键点击开始绘制',popOffset);
        }
        if (_this._drawingPositions.length > 0  && _this._drawingPositions.length < 4  ) {
          mouseHelper.updateHelper(evt.endPosition, '左键点击继续绘制',popOffset);
        }
        if (_this._drawingPositions.length >= 4) {
          mouseHelper.updateHelper(evt.endPosition, '左键点击继续绘制，右键点击结束绘制',popOffset);
        }
        if(_this._drawingPositions.length>0){
          _this._drawingPositions.pop();
          _this._drawingPositions.push(car3);
          console.log("当前选择的",_this._drawingPositions)
          if (!_this._drawingPolyline) {
            _this._drawingPolyline = _this.createDynamicPolyline(Polyline);
          }
          if (!_this._drawingPolygon) {
            _this._drawingPolygon = _this.createDynamicPolygon(Polygon);
           let computeArea=  _this.createAreaLabelBz();
           _this._drawingEntity.push(computeArea);
          }
        }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    //鼠标右键事件
    handler.setInputAction(function(evt: any) {
      let car3 = gisTools.getCar3Position(cviewer,evt.position);
      if(_this._drawingPositions.length>3){
        _this.rightHandler(_this,car3)
      }
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  rightHandler(_this:any,car3:any){
    //当前鼠标右键的操作点位记录
    _this._drawingPositions.push(car3);
    //鼠标动态绘制过程的点+1
    _this._drawingPositions.push(car3);
    //右键直接结束创建尾点
    _this.createPoint(car3.clone());
    //如果是一次绘制，绘制结束完，清除事件
    _this.isDrawingEnd = true;
    _this.endDrawing();
  }
  /**
   *结束绘制的事件
   */
  endDrawing() {
    if(handler){
      handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
      handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    }
    mouseHelper.removeHelper();
    return true;
  }

  /**
   * 清除绘制的Graphic
   */
  clearDrawGraphic() {
    this._drawingPositions = [];
    this.endDrawing();
    if(this._drawingPolygon.length>0){
      this._drawingPolygon.forEach((item:any)=>{
        cviewer.entities.remove(item)
      })
    }
    if(this._drawingEntity.length>0){
      this._drawingEntity.forEach((item:any)=>{
        cviewer.entities.remove(item)
      })
    }
    this.isDrawingEnd=false;
    this._drawingPolygon = null;
    this._drawingPositions = [];
    return true;
  }


  /**
   * 创建面积标注
   * @param cartesian
   * @param textArea
   */
  createAreaLabelBz() {
    let _this=this;
    var point = cviewer.entities.add({
      position: new Cesium.CallbackProperty(function() {
        let polyCenter = Cesium.BoundingSphere.fromPoints(_this._drawingPositions).center;//中心点
        polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
        return polyCenter;
      }, false),
      label: {
        text: new Cesium.CallbackProperty(function() {
          return  _this.getArea(_this._drawingPositions)+"平方公里"
        }, false),
        font: '18px sans-serif',
        fillColor: Cesium.Color.GOLD,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(20, -40),
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
      }
    });
    return point;
  }

  /**
   * 创建面
   * @param positionArr-绘制过程中的动态的面
   * @param style
   */
  createDynamicPolygon(style: any) {
    if(!style){
       style={
         fill:'#DC143C',
         opacity:0.1,
         stroken:'#DC143C',
         width:3
       }
    }
    style['fill'] = style?.fill ?? '#DC143C';
    style['opacity'] = style?.opacity ?? 0.1;
    style['stroken'] = style?.stroken ?? '#DC143C';
    style['width'] = style?.width ?? 3;
    let _this = this;
    var polygon = cviewer.entities.add({
      polygon: {
        hierarchy: new Cesium.CallbackProperty(function() {
          return new Cesium.PolygonHierarchy(_this._drawingPositions);
        }, false),
        clampToGround: true,
        show: true,
        fill: true,
        material: Cesium.Color.fromCssColorString(style.fill).withAlpha(style.opacity),
        width: style.width,
        outlineColor: Cesium.Color.fromCssColorString(style.stroken),
        outlineWidth: 1,
        outline: false,
      },
    });
    return polygon;
  }



  /**
   * 添加的是多边形的顶点
   * @param cartesian
   */
  createPoint(cartesian:any) {
    var point = cviewer.entities.add({
      position: cartesian,
      point: {
        pixelSize: 10,
        color: Cesium.Color.YELLOW,
      }
    });
    this._drawingEntity.push(point);
    return point;
  }
  createDynamicPolyline(style:any) {
    if(!style){
      style={
        stroken:"#DC143C",
        width:3
      }
    }
    style['stroken'] = style?.stroken ?? '#DC143C';
    style['width'] = style?.width ?? 3;
    let $this = this;
    let polyline =cviewer.entities.add({
      id: 'area_search_draw_graphic_polygon' + new Date().getTime(),
      polyline: {
        //使用cesium的peoperty
        positions: new Cesium.CallbackProperty(function () {
          let carArr:any=$this._drawingPositions;
          let newCarArr:any=[];
          //避免数据改变（_drawingPositions）的影响
          carArr.forEach((item:any)=>{
            newCarArr.push(item.clone());
          })
          //为了线首位相连
          newCarArr.push(newCarArr[0]);
          return newCarArr
        }, false),
        show: true,
        material: Cesium.Color.RED,
        width: 3,
        clampToGround: true
      }
    });
    return  polyline;
  }

  //计算多边形面积
  /**
   *
   * @param points Car3 数组
   */
  getArea(points:any) {
    var res = 0;
    //拆分三角曲面
    for (var i = 0; i < points.length - 2; i++) {
      var j = (i + 1) % points.length;
      var k = (i + 2) % points.length;
      var totalAngle = this.Angle(points[i], points[j], points[k]);

      var dis_temp1 = this.distance(points[i], points[j]);
      var dis_temp2 = this.distance(points[j], points[k]);
      res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle));
    }

    return (res / 1000000.0).toFixed(4);
  }

  /*角度*/
  /**
   * 计算角度
   * @param p1 Car3
   * @param p2 Car3
   * @param p3 Car3
   * @constructor
   */
  Angle(p1:any, p2:any, p3:any) {
    var bearing21 = this.Bearing(p2, p1);
    var bearing23 = this.Bearing(p2, p3);
    var angle = bearing21 - bearing23;
    if (angle < 0) {
      angle += 360;
    }
    return angle;
  }

  /*方向*/
  /**
   * 方向
   * @param from Car3
   * @param to Car3
   * @constructor
   */
  Bearing(from:any, to:any) {
    var radiansPerDegree = Math.PI / 180.0;//角度转化为弧度(rad)
    var degreesPerRadian = 180.0 / Math.PI;//弧度转化为角度
    var cartographic_from = Cesium.Cartographic.fromCartesian(from);
    var cartographic_to = Cesium.Cartographic.fromCartesian(to);
    var lon_from = Cesium.Math.toDegrees(cartographic_from.longitude);
    var lat_from = Cesium.Math.toDegrees(cartographic_from.latitude);

    var lon_to = Cesium.Math.toDegrees(cartographic_to.longitude);
    var lat_to = Cesium.Math.toDegrees(cartographic_to.latitude);

    var lat1 = lat_from * radiansPerDegree;
    var lon1 = lon_from * radiansPerDegree;
    var lat2 = lat_to * radiansPerDegree;
    var lon2 = lon_to * radiansPerDegree;
    var angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
    if (angle < 0) {
      angle += Math.PI * 2.0;
    }
    angle = angle * degreesPerRadian;//角度
    return angle;
  }

  /**
   *  计算距离
   * @param point1  Car3
   * @param point2  Car3
   */
  distance(point1:any, point2:any) {
    var point1cartographic = Cesium.Cartographic.fromCartesian(point1);
    var point2cartographic = Cesium.Cartographic.fromCartesian(point2);
    /**根据经纬度计算出距离**/
    var geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(point1cartographic, point2cartographic);
    var s = geodesic.surfaceDistance;
    //返回两点之间的距离
    s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
    return s;
  }


}



export default MeasurePolygon;

`);

onMounted(() => {
  cViewer.value = initMap("load4490_box")
  loadTdtLayer(cViewer.value, 'c', false);
})
const measureEvent=(type:string)=>{
  let xoffset= document.body.clientWidth*0.4;
  if(type==='point'){
    point= new  measurePoint(cViewer.value);
    point.startMeasure({popOffset:{x:xoffset,y:72}})
  }else if(type==="line"){
    polyline= new  measureLine(cViewer.value);
    polyline.startMeasure({popOffset:{x:xoffset,y:72}})
  }else if(type==="polygon"){
    polygon= new  measurePolygon(cViewer.value);
    polygon.startMeasure({popOffset:{x:xoffset,y:72}})
  }
}
const removeAll=()=>{
  if(point){
    point.clearDrawGraphic();
  }
  if(polyline){
    polyline.clearDrawGraphic();
  }
  if(polygon){
    polygon.clearDrawGraphic();
  }
}
</script>

<style lang="scss" scoped>
.left_box {
  width: 40%;
  height: 100%;
  display: flex;
  flex-direction: row-reverse;

  .code_box {
    margin: 10px;
    width: calc(100% - 220px);
    height: calc(100% - 20px);
    //border:1px solid #00ff00;
    background-color: #ffffff;
    color: #000;
    overflow-x: hidden;
    overflow-y: auto;
  }
}

#load4490_box {
  width: 60%;
  height: 100%;
}

.popup_box {
  position: fixed;
  left: calc(40% + 100px);
  width: 200px;
  top: 100px;
  height: 60px;
  z-index: 10;
}

.inner_content_common {
  margin-top: 10px;
  display: flex;
  justify-content: center;
  width: 50%;
}
</style>
